package com.bolt.report.engine;

import com.bolt.common.bean.BeanUtil;
import com.bolt.common.convert.Convert;
import com.bolt.common.utils.StrUtil;
import com.bolt.report.definition.SortOrder;
import com.bolt.report.exception.ReportException;
import com.bolt.report.util.ToolUtil;

import java.math.BigDecimal;
import java.util.*;

public class CollectionDataSource extends AbstractBeanDataSource {

    private List<?> data;
    private Iterator<?> iterator;
    private Object currentBean;

    public CollectionDataSource(List<?> beanCollection) {
        this.data = beanCollection;
        if (this.data != null) {
            this.iterator = this.data.iterator();
        }
    }

    @Override
    public boolean next() {
        boolean hasNext = false;
        if (this.iterator != null) {
            hasNext = this.iterator.hasNext();
            if (hasNext) {
                this.currentBean = this.iterator.next();
            }
        }
        return hasNext;
    }

    public Object getCurrentData() {
        return currentBean;
    }

    @Override
    public Object getFieldValue(BRField field) throws ReportException {
        return getFieldValue(currentBean, field);
    }

    public String getFieldValue(String fieldName) throws ReportException {
        if (StrUtil.isNotBlank(fieldName)) {
            Object value = getFieldValue(currentBean, fieldName);
            return Convert.toStr(value, StrUtil.EMPTY);
        } else {
            return null;
        }

    }

    @Override
    public void sort(BRSortField[] sortFields) {
        Comparator<Object> mainComparator = null;
        for (int i = 0; i < sortFields.length; i++) {
            BRSortField sortField = sortFields[i];
            Comparator<Object> comparator = new Comparator() {
                @Override
                public int compare(Object data1, Object data2) {
                    return doOrder(data1, data2, sortField);
                }
            };
            if (sortField.getSortOrder().equals(SortOrder.DESC)) {
                comparator = comparator.reversed();
            }
            if (i > 0) {
                mainComparator = mainComparator.thenComparing(comparator);
            } else {
                mainComparator = comparator;
            }
        }
        Collections.sort(this.data, mainComparator);
        this.iterator = this.data.iterator();
    }

    private int doOrder(Object data1, Object data2, BRSortField sortField) {
        if (data1 == null || data2 == null) {
            return 1;
        }
        Object field1 = BeanUtil.getFieldValue(data1, sortField.getName());
        Object field2 = BeanUtil.getFieldValue(data2, sortField.getName());
        if (field1 == null || field2 == null) {
            return 1;
        }
        if (field1 instanceof Date) {
            Date d1 = (Date) field1;
            Date d2 = (Date) field2;
            return d1.compareTo(d2);
        } else if (field1 instanceof Number) {
            BigDecimal n1 = ToolUtil.toBigDecimal(field1);
            BigDecimal n2 = ToolUtil.toBigDecimal(field2);
            return n1.compareTo(n2);
        } else {
            String str1 = field1.toString();
            String str2 = field2.toString();
            return str1.compareTo(str2);

        }
    }

    public List<?> getData() {
        return this.data;
    }
}